package com.xc.disk.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xc.disk.bean.DrawCodeBean;
import com.xc.disk.bean.FolderFileBean;
import com.xc.disk.bean.ShareBean;
import com.xc.disk.dto.DrawCodeDto;
import com.xc.disk.dto.FolderDto;
import com.xc.disk.entity.FileEntity;
import com.xc.disk.entity.FolderEntity;
import com.xc.disk.entity.ShareEntity;
import com.xc.disk.entity.ShareFileEntity;
import com.xc.disk.exception.OperateException;
import com.xc.disk.info.TokenInfo;
import com.xc.disk.mapper.FileMapper;
import com.xc.disk.mapper.FolderMapper;
import com.xc.disk.mapper.ShareFileMapper;
import com.xc.disk.mapper.ShareMapper;
import com.xc.disk.service.FileService;
import com.xc.disk.service.FolderService;
import com.xc.disk.service.ShareService;
import com.xc.tool.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <p>项目名称: Stars</p>
 * <p>描述: 共享文件实现</p>
 * <P>创建人:小程 </p>
 * <P>创建人邮箱: 779943476@qq.com</p>
 * <p>创建时间: 2019/11/25</p>
 *
 * @version v1.0
 */
@Service
@Slf4j
public class ShareServiceImpl extends ServiceImpl<ShareMapper, ShareEntity> implements ShareService {

    @Autowired
    private ShareFileMapper shareFileMapper;
    @Autowired
    private FolderService folderService;
    @Autowired
    private FolderMapper folderMapper;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private ShareMapper shareMapper;
    @Autowired
    private FileService fileService;

    @Override
    @Transactional
    public ShareEntity createShare(TokenInfo token, ShareBean shareBean) {
        //创建共享文件
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setValidTime(shareBean.getValidTime());
        if (shareBean.getNeedCode()) {
            String drawCode = StringUtils.random(6);
            shareEntity.setDrawCode(drawCode);
        }
        shareEntity.setUserId(token.getUserId());
        shareEntity.setCode(UUID.randomUUID().toString());
        List<FolderFileBean> folderFiles = shareBean.getFolderFiles();
        if (folderFiles == null || folderFiles.size() == 0) {
            throw new OperateException("f035", "共享文件id必传");
        }
        FolderFileBean folder = folderFiles.get(0);
        if (folder.getIsFile()) {
            FileEntity fileEntity = fileMapper.selectById(folder.getId());
            if (folderFiles.size() == 1) {
                shareEntity.setName(fileEntity.getName());
            } else {
                shareEntity.setName(fileEntity.getName() + "等");
            }
        } else {
            FolderEntity folderEntity = folderMapper.selectById(folder.getId());
            if (folderFiles.size() == 1) {
                shareEntity.setName(folderEntity.getName());
            } else {
                shareEntity.setName(folderEntity.getName() + "等");
            }
        }
        if (!this.save(shareEntity)) {
            throw new OperateException("f035", "创建共享文件失败！");
        }
        for (FolderFileBean folderFileBean : folderFiles) {
            if (folderFileBean.getIsFile()) {
                //文件共享
                FileEntity fileEntity = fileMapper.selectById(folderFileBean.getId());
                if (!fileEntity.getUserId().equals(token.getUserId())) {
                    throw new OperateException("f027", "你的账号没有操作该数据的权限！");
                }
                ShareFileEntity shareFileEntity = new ShareFileEntity();
                shareFileEntity.setShareId(shareEntity.getId());
                shareFileEntity.setRootId(fileEntity.getId());
                if (!retBool(shareFileMapper.insert(shareFileEntity))) {
                    throw new OperateException("f037", "关联文件失败！");
                }
                ShareFileEntity share = new ShareFileEntity();
                share.setShareId(shareEntity.getId());
                share.setFileId(fileEntity.getId());
                if (!retBool(shareFileMapper.insert(share))) {
                    throw new OperateException("f037", "关联文件失败！");
                }
            } else {
                //文件共享
                FolderEntity folderEntity = folderMapper.selectById(folderFileBean.getId());
                if (!folderEntity.getUserId().equals(token.getUserId())) {
                    throw new OperateException("f027", "你的账号没有操作该数据的权限！");
                }
                ShareFileEntity shareFileEntity = new ShareFileEntity();
                shareFileEntity.setShareId(shareEntity.getId());
                shareFileEntity.setRootId(folderEntity.getId());
                if (!retBool(shareFileMapper.insert(shareFileEntity))) {
                    throw new OperateException("f037", "关联文件失败！");
                }
                //创建下级共享文件关联
                folderService.subdirectoryHandle(folderFileBean.getId(), null, (subdirectoryInfo) -> {
                    if (subdirectoryInfo.getIsFile()) {
                        List<FileEntity> files = subdirectoryInfo.getFiles();
                        for (FileEntity file : files) {
                            //文件共享
                            if (!file.getUserId().equals(token.getUserId())) {
                                throw new OperateException("f027", "你的账号没有操作该数据的权限！");
                            }
                            ShareFileEntity share = new ShareFileEntity();
                            share.setFileId(file.getId());
                            share.setShareId(shareEntity.getId());
                            if (!retBool(shareFileMapper.insert(share))) {
                                throw new OperateException("f037", "关联文件失败！");
                            }
                        }
                    }
                });
            }
        }
        return shareEntity;
    }

    @Override
    public List<ShareEntity> getShareFileListByUserId(TokenInfo token) {
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setUserId(token.getUserId());
        return list(new QueryWrapper<>(shareEntity));
    }

    @Override
    @Transactional
    public void deleteShareFile(TokenInfo token, List<String> ids) {
        for (String id : ids) {
            QueryWrapper<ShareFileEntity> queryWrapper = new QueryWrapper<>(new ShareFileEntity(id));
            if (shareFileMapper.selectList(queryWrapper).size() != 0) {
                if (!retBool(shareFileMapper.delete(queryWrapper))) {
                    throw new OperateException("f038", "取消共享关联失败！");
                }
            }
        }
        if (!this.removeByIds(ids)) {
            throw new OperateException("f038", "取消共享文件失败！");
        }
    }

    @Override
    public DrawCodeDto inspectDrawCode(String code) {
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setCode(code);
        shareEntity = shareMapper.selectOne(new QueryWrapper<>(shareEntity));
        if (shareEntity == null) {
            throw new OperateException("", "共享信息不存在！");
        }
        if (shareEntity.getDrawCode() == null || shareEntity.getDrawCode().equals("")) {
            return new DrawCodeDto(shareEntity.getId());
        } else {
            return null;
        }
    }

    @Override
    public DrawCodeDto verifyDrawCode(DrawCodeBean drawCodeBean) {
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setCode(drawCodeBean.getCode());
        shareEntity = shareMapper.selectOne(new QueryWrapper<>(shareEntity));
        if (shareEntity == null) {
            throw new OperateException("", "共享信息不存在！");
        }
        if (shareEntity.getDrawCode() == null || !shareEntity.getDrawCode().equals(drawCodeBean.getDrawCode())) {
            throw new OperateException("", "你的提取码不正确！");
        }
        return new DrawCodeDto(shareEntity.getId());
    }

    @Override
    public FolderDto getShareFile(String fid, String parentId) {
        FolderDto folderDto = new FolderDto();
        ShareEntity shareEntity = this.getById(fid);
        if ((shareEntity.getCreateTime().getTime() + shareEntity.getValidTime()) < System.currentTimeMillis()) {
            throw new OperateException("", "共享文件已失效！");
        }
        //根据共享id查询共享关联
        List<ShareFileEntity> shareFiles = shareFileMapper.selectList(new QueryWrapper<>(new ShareFileEntity(shareEntity.getId())));
        if (shareFiles == null || shareFiles.size() == 0) {
            throw new OperateException("", "共享文件不存在！");
        }
        //查询遍历
        List<String> parentIds = new ArrayList<>();
        List<String> fileIds = new ArrayList<>();
        List<String> queryFileIds = new ArrayList<>();
        for (ShareFileEntity shareFileEntity : shareFiles) {
            if (shareFileEntity.getRootId() != null) {
                parentIds.add(shareFileEntity.getRootId());
                fileIds.add(shareFileEntity.getRootId());
            } else {
                queryFileIds.add(shareFileEntity.getFileId());
            }
        }
        if (parentId == null || parentId.equals("")) {
            //首次查询
            //查目录
            QueryWrapper<FolderEntity> queryWrapper = new QueryWrapper<>(new FolderEntity()).in("id", parentIds);
            List<FolderEntity> folders = folderMapper.selectList(queryWrapper);
            folderDto.setFolders(folders);
            //查文件
            QueryWrapper<FileEntity> query = new QueryWrapper<>(new FileEntity());
            query.in("id", fileIds);
            List<FileEntity> files = fileMapper.selectList(query);
            folderDto.setFiles(files);
        } else {
            //查询下级
            //查目录
            FolderEntity folderEntity = new FolderEntity();
            folderEntity.setParentId(parentId);
            List<FolderEntity> folders = folderMapper.selectList(new QueryWrapper<>(folderEntity));
            folderDto.setFolders(folders);
            //查文件
            FileEntity fileEntity = new FileEntity();
            fileEntity.setFolderId(parentId);
            QueryWrapper<FileEntity> query = new QueryWrapper<>(fileEntity);
            query.in("id", queryFileIds);
            List<FileEntity> files = fileMapper.selectList(query);
            folderDto.setFiles(files);
        }
        return folderDto;
    }

    @Override
    public String downloadShareFile(String shareId, String fid) {
        ShareFileEntity shareFileEntity = new ShareFileEntity();
        shareFileEntity.setFileId(fid);
        shareFileEntity.setShareId(shareId);
        ShareFileEntity shareFileEntity1 = shareFileMapper.selectOne(new QueryWrapper<>(shareFileEntity));
        if (shareFileEntity1 != null) {
            FileEntity fileEntity = fileService.getFileById(fid);
            return fileService.getDownloadUrl(fileEntity);
        } else {
            throw new OperateException("", "文件不存在！");
        }
    }

    @Override
    public void saveShare(TokenInfo token, String shareId, String folderId) {
        // 查询文件
        long size = 0;
        List<ShareFileEntity> shareFiles = shareFileMapper.selectList(new QueryWrapper<>(new ShareFileEntity(shareId)));
        List<String> fileIds = new ArrayList<>();
        List<String> folderIds = new ArrayList<>();
        for (ShareFileEntity shareFileEntity : shareFiles) {
            if (shareFileEntity.getRootId() != null) {
                fileIds.add(shareFileEntity.getRootId());
                folderIds.add(shareFileEntity.getRootId());
            }
        }
        // 保存下级文件
        List<FolderEntity> folders = folderMapper.selectBatchIds(folderIds);
        for (FolderEntity folderEntity : folders) {
            size = +folderEntity.getSize();
            folderEntity.setUserId(token.getUserId());
            folderEntity.setParentId(folderId);
            folderEntity.setId(null);
            folderEntity.setCreateTime(null);
            folderEntity.setUpdateTime(null);
            folderEntity.setVersion(null);
            if (!retBool(folderMapper.insert(folderEntity))) {
                throw new OperateException("", "目录保存失败");
            }
            //复制文件及以下目录
            folderService.subdirectoryHandle(
                    folderEntity.getId(),
                    folderEntity.getId(),
                    (subdirectoryInfo) -> {
                        if (subdirectoryInfo.getIsFile()) {
                            List<FileEntity> files = subdirectoryInfo.getFiles();
                            for (FileEntity fileEntity : files) {
                                //复制文件
                                fileEntity.setId(null);
                                fileEntity.setUpdateTime(null);
                                fileEntity.setCreateTime(null);
                                fileEntity.setVersion(null);
                                fileEntity.setFolderId(subdirectoryInfo.getNewParentId());
                                if (!retBool(fileMapper.insert(fileEntity))) {
                                    throw new OperateException("f030", "创建文件失败！");
                                }
                            }
                        } else {
                            FolderEntity folder = subdirectoryInfo.getFolder();
                            //复制目录
                            folder.setId(null);
                            folder.setCreateTime(null);
                            folder.setUpdateTime(null);
                            folder.setVersion(null);
                            folder.setParentId(subdirectoryInfo.getNewParentId());
                            if (!this.retBool(folderMapper.insert(folder))) {
                                throw new OperateException("f028", "创建目录失败！");
                            }
                        }
                    });
        }

        //保存文件
        List<FileEntity> files = fileMapper.selectBatchIds(fileIds);
        for (FileEntity fileEntity : files) {
            fileEntity.setUserId(token.getUserId());
            fileEntity.setFolderId(folderId);
            fileEntity.setId(null);
            fileEntity.setCreateTime(null);
            fileEntity.setUpdateTime(null);
            fileEntity.setVersion(null);
            size += fileEntity.getSize();
        }
        if (!fileService.saveBatch(files)) {
            throw new OperateException("", "保存文件失败！");
        }
        //加法计算文件大小
        folderService.addFolderSize(folderId, size);
    }
}
